package zone.czh.woi.woim.server.channel.protocol.builder;

import io.netty.channel.*;
import lombok.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import zone.czh.woi.base.util.Pair;
import zone.czh.woi.woim.base.channel.adapter.ProtocolAdapter;
import zone.czh.woi.woim.base.channel.constant.ChannelHandlerName;
import zone.czh.woi.woim.base.channel.protocol.builder.ProtocolBuilder;
import zone.czh.woi.woim.server.constant.AttributeKeyConstant;
import zone.czh.woi.woim.server.util.AttributeKeyUtil;

import java.util.List;
import java.util.Map;
/**
*@ClassName: ServerProtocolBuilder
*@Description: None
*@author woi
*/
@NoArgsConstructor
@AllArgsConstructor
public class ServerProtocolBuilder implements ProtocolBuilder {
    Logger log = LoggerFactory.getLogger(ServerProtocolBuilder.class);
    @Getter@Setter
    Map<String,ProtocolAdapter> protocolAdapters;

    public ServerProtocolBuilder(Map<String, ProtocolAdapter> protocolAdapters) {
        this.protocolAdapters=protocolAdapters;
    }

    @Override
    public void build(ChannelPipeline pipeline, String protocolName) {
        if (protocolAdapters!=null){
            ProtocolAdapter adapter = protocolAdapters.get(protocolName);
            if (adapter==null){
                throw new RuntimeException("no adapter for protocol:"+protocolName);
            }
            pipeline.addBefore(ChannelHandlerName.PAYLOAD_HANDLER,protocolName,adapter);
            List<Pair<String, ChannelInboundHandler>> decoderPairs = adapter.getDecoders();
            List<Pair<String, ChannelOutboundHandler>> encoderPairs = adapter.getEncoders();
            if(decoderPairs!=null){
                //decoder
                for (int i=0;i<decoderPairs.size();++i){
                    ChannelInboundHandler decoder = decoderPairs.get(i).getValue();
                    String name = decoderPairs.get(i).getKey();
                    pipeline.addBefore(protocolName,name!=null?name:protocolName+"-decoder-"+i,decoder);
                }
            }
            if (encoderPairs!=null){
                //encoder
                for (int i=0;i<encoderPairs.size();++i){
                    ChannelOutboundHandler encoder = encoderPairs.get(i).getValue();
                    String name = encoderPairs.get(i).getKey();
                    pipeline.addBefore(ChannelHandlerName.PAYLOAD_ENCODER,name!=null?name:protocolName+"-encoder-"+i,encoder);
                }
            }
            AttributeKeyUtil.set(pipeline.channel(), AttributeKeyConstant.PROTOCOL,protocolName);
            log.debug("Protocol:{} for channel:{} has been set",protocolName,pipeline.channel().id());
        }
    }
}
